package uk.co.q3c.deplan.server.util.validation;

import java.util.List;

import uk.co.q3c.deplan.server.util.rules.RuleManager;
import uk.co.q3c.deplan.server.util.validation.rules.PropertyValuer;
import uk.co.q3c.deplan.server.util.validation.rules.ValidationObjectRule;
import uk.co.q3c.deplan.server.util.validation.rules.ValidationPropertyRule;

public class Validator extends RuleManager<ValidationPropertyRule, ValidationObjectRule> {

	private static final long serialVersionUID = 1L;

	public Validator(PropertyValuer parent) {
		super(parent);
	}

	public ValidationResult validate(String propertyName, Object propertyValue) {

		ValidationResult vr = new ValidationResult();
		List<ValidationPropertyRule> pvs = propertyRules(propertyName);
		// if there are no rules set, can't fail them
		if (pvs == null) {
			vr.setValid(true);
			return vr;
		}
		boolean overallPass = true;
		for (ValidationPropertyRule vrule : pvs) {
			vrule.validate(propertyName, propertyValue, vr);
			if (vr.isNotValid()) {
				overallPass = false;
			}
		}
		vr.setValid(overallPass);
		return vr;
	}

	/**
	 * A {@link ValidationResult} is returned with the results of the validation including any error messages. To assess whether successful,
	 * call {@link #validateObject()} and test {@link ValidationResult#isValid()}
	 * 
	 * @return ValidationResult
	 */
	public ValidationResult validateObject() {
		ValidationResult vr = new ValidationResult();
		boolean overallPass = true;
		for (ValidationObjectRule ovr : objectRules()) {
			ovr.validate(getParent(), vr);
			if (vr.isNotValid()) {
				overallPass = false;
			}
		}
		vr.setValid(overallPass);
		return vr;
	}

	/**
	 * A {@link ValidationResult} is returned with the results of the validation including any error messages. To assess whether successful,
	 * call {@link #validateObject()} and test {@link ValidationResult#isValid()}
	 * 
	 * @return ValidationResult
	 */
	public ValidationResult validate(String propertyName) {
		Object propertyValue = getParent().propertyValue(propertyName);
		return validate(propertyName, propertyValue);
	}
}
